package com.yfbao.horizon.schedule.tk.utils;

import net.jpountz.lz4.LZ4Compressor;
import net.jpountz.lz4.LZ4Factory;
import net.jpountz.lz4.LZ4FastDecompressor;

//缓存压缩读写
public class LZ4Compress {

    public static CompressCacheDto compressObject(Object object){
        CompressCacheDto cacheVo = new CompressCacheDto();
        byte[] serialize = KryoSerialization.serializeObject(object);
        byte[] compress = compress(serialize);
//        Byte[] bytes = toObjects(compress);
        cacheVo.setData(compress);
        cacheVo.setSrcLength(serialize.length);
        return cacheVo;
    }

    public static<V> V decompressionToObject(CompressCacheDto cacheVo){
//        byte[] bytes = toPrimitives(cacheVo.getData());
//        byte[] compress = decompression(bytes,cacheVo.getSrcLength());

        byte[] compress = decompression(cacheVo.getData(),cacheVo.getSrcLength());
        V deserialize = (V) KryoSerialization.deserializeObject(compress);
        return deserialize;
    }

    public static byte[] compressObjectTobytes(Object object){
        CompressCacheDto cacheVo = new CompressCacheDto();
        byte[] serialize = KryoSerialization.serializeObject(object);
        byte[] compress = compress(serialize);
        byte[] bytes = intToBytes(serialize.length);
        byte[] result = new byte[4+compress.length];
        System.arraycopy(bytes,0,result,0,4);
        System.arraycopy(compress,0,result,4,compress.length);
        return result;
    }

    public static<V> V decompressionToObject(byte[] result){
        byte[] bytes = new byte[4];
        System.arraycopy(result,0,bytes,0,4);
        int length = bytesToInt(bytes);
        byte[] compress = new byte[result.length-4];
        System.arraycopy(result,4,compress,0,result.length-4);
        byte[] decompress = decompression(compress,length);
        V deserialize = (V) KryoSerialization.deserializeObject(decompress);
        return deserialize;
    }


    public static byte[] compress(byte[] data) {
        LZ4Factory factory = LZ4Factory.fastestInstance();
        LZ4Compressor compressor = factory.fastCompressor();
        byte[] srccompress = compressor.compress(data);
        return srccompress;
    }


    public static byte[] decompression(byte[] data, int srcLength) {
        LZ4Factory factory = LZ4Factory.fastestInstance();
        LZ4FastDecompressor lz4FastDecompressor = factory.fastDecompressor();
        return lz4FastDecompressor.decompress(data,srcLength);
    }


    /**
     * 将int数值转换为占四个字节的byte数组，(高位在前，低位在后的顺序)。
     *
     * @param value 要转换的int值
     * @return byte数组
     */
    public static byte[] intToBytes(int value) {
        byte[] src = new byte[4];
        src[0] = (byte) ((value >> 24) & 0xFF);
        src[1] = (byte) ((value >> 16) & 0xFF);
        src[2] = (byte) ((value >> 8) & 0xFF);
        src[3] = (byte) (value & 0xFF);
        return src;
    }

    /**
     * 将占四个字节的byte数组转换为int数值，(高位在前，低位在后的顺序)。
     *
     * @param src 占四个字节的byte数组
     * @return int数值
     */
    public static int bytesToInt(byte[] src) {
        int value;
        value = (((src[0] & 0xFF) << 24)
                | ((src[1] & 0xFF) << 16)
                | ((src[2] & 0xFF) << 8)
                | (src[3] & 0xFF));
        return value;
    }


    private static Byte[] toObjects(byte[] bytesPrim){
        Byte[] bytes = new Byte[bytesPrim.length];
        int i = 0;
        for (byte b : bytesPrim){
            bytes[i++] = b; // Autoboxing
        }
        return bytes;
    }

    public static byte[] toPrimitives(Byte[] oBytes) {
        byte[] bytes = new byte[oBytes.length];
        for (int i = 0; i < oBytes.length; i++) {
            bytes[i] = oBytes[i];
        }
        return bytes;
    }
}
